using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using AForge.Imaging.Filters;
using System.Text;

namespace PBR.Filters
{
    public class AlphaMatteFromColor
    {
        public void ApplyInPlace(Bitmap matteImage, Bitmap toMatteImage)
        {
            if (matteImage.PixelFormat != PixelFormat.Format8bppIndexed || toMatteImage.PixelFormat != PixelFormat.Format32bppArgb)
            {
                throw new ArgumentException("AlphaMatte Apply takes one grayscale and one RBGA image");
            }
            if (matteImage.Width != toMatteImage.Width || matteImage.Height != toMatteImage.Height)
            {
                throw new ArgumentException("AlphaMatte Apply takes 2 same size images");
            }

            BitmapData matteData = matteImage.LockBits(
                new Rectangle(0, 0, matteImage.Width, matteImage.Height),
                ImageLockMode.ReadOnly, matteImage.PixelFormat);

            BitmapData toMatteData = toMatteImage.LockBits(
                new Rectangle(0, 0, toMatteImage.Width, toMatteImage.Height),
                ImageLockMode.ReadWrite, toMatteImage.PixelFormat);

            // process the filter
            ProcessFilter(matteData, toMatteData);

            // unlock destination images
            matteImage.UnlockBits(matteData);
            toMatteImage.UnlockBits(toMatteData);

            return;
        }

        private unsafe void ProcessFilter(BitmapData matteData, BitmapData toMatteData)
        {
            // get width and height
            int width = matteData.Width;
            int height = matteData.Height;

            int toMatteOffset = toMatteData.Stride - width * 4;
            int matteOffset = matteData.Stride - width;

            // do the job
            byte* mattePtr = (byte*)matteData.Scan0.ToPointer();
            byte* toMattePtr = (byte*)toMatteData.Scan0.ToPointer();

            // for each line
            for (int y = 0; y < height; y++)
            {
                // for each pixel
                for (int x = 0; x < width; x++, mattePtr += 1, toMattePtr += 4)
                {
                    toMattePtr[AForge.Imaging.RGBA.A] = (byte)((toMattePtr[AForge.Imaging.RGBA.A] * (*mattePtr)) / 255);
                }
                mattePtr += matteOffset;
                toMattePtr += toMatteOffset;
            }
        }
    }
}
